home *** CD-ROM | disk | FTP | other *** search
- from zope.interface import implements
-
- from nevow import inevow
-
-
- def languagesFactory(ctx):
- header = inevow.IRequest(ctx).getHeader('accept-language')
- if header is None:
- return []
- langs = []
- for lang in header.split(','):
- quality = 1.0
- if ';' in lang:
- lang, quality = lang.split(';', 1)
- if quality[:2] == 'q=':
- try:
- quality = float(quality[2:])
- except ValueError:
- pass
- langs.append((quality, lang))
- if '-' in lang:
- langs.append((quality, lang.split('-')[0]))
- langs.sort(lambda a,b: cmp(b[0], a[0]))
- return [lang for quality, lang in langs]
-
-
- class I18NConfig(object):
- implements(inevow.II18NConfig)
-
- def __init__(self,
- domain=None,
- localeDir=None,
- ):
- self.domain = domain
- self.localeDir = localeDir
-
- class PlaceHolder(object):
- def __init__(self, translator, *args, **kwargs):
- self.translator = translator
- self.args = args
- self.kwargs = kwargs
- _mod = kwargs.pop('_mod', None)
- if _mod is None:
- _mod = []
- self.mod = _mod
-
- def __mod__(self, other):
- kw = {}
- kw.update(self.kwargs)
- kw['_mod'] = self.mod+[other]
- return self.__class__(self.translator,
- *self.args,
- **kw)
-
- def __repr__(self):
- args = []
- if self.args:
- args.append('*%r' % (self.args,))
- args.append('translator=%r' % self.translator)
- if self.kwargs:
- args.append('**%r' % self.kwargs)
- s = '%s(%s)' % (
- self.__class__.__name__,
- ', '.join(args),
- )
- for mod in self.mod:
- s += ' %% %r' % (mod,)
- return s
-
- def flattenL10n(placeHolder, ctx):
- kw = placeHolder.kwargs
-
- try:
- languages = inevow.ILanguages(ctx)
- except TypeError:
- pass
- else:
- kw = dict(kw) # copy before we mutate it
- kw['languages'] = languages
-
- try:
- cfg = inevow.II18NConfig(ctx)
- except TypeError:
- pass
- else:
- kw = dict(kw) # copy before we mutate it
- if cfg.domain is not None:
- kw['domain'] = cfg.domain
- if cfg.localeDir is not None:
- kw['localeDir'] = cfg.localeDir
-
- s = placeHolder.translator(*placeHolder.args, **kw)
- for mod in placeHolder.mod:
- s = s % mod
- return s
-
-
- class Translator(object):
- """
- A gettext-like Translator for Nevow.
-
- The major difference between this and naive gettext is that with
- Translator, the actual translation is done as part of Nevow's
- flattening process, allowing per-user settings to be retrieved via
- the context.
-
- @ivar translator: the actual translation function to use.
-
- @ivar args: positional arguments to pass to translator.
-
- @ivar kwargs: keyword arguments to pass to translator.
-
- @ivar gettextFunction: If using the default translator function,
- name of GNU gettext function to wrap. Useful for 'ungettext'.
- """
- translator = None
- args = None
- kwargs = None
-
- gettextFunction = 'ugettext'
-
- def _gettextTranslation(self, *args, **kwargs):
- domain = kwargs.pop('domain', None)
- localeDir = kwargs.pop('localeDir', None)
- languages = kwargs.pop('languages', None)
- import gettext
- translation = gettext.translation(
- domain=domain,
- localedir=localeDir,
- languages=languages,
- fallback=True,
- )
- fn = getattr(translation,
- self.gettextFunction)
- return fn(*args, **kwargs)
-
- def __init__(self, **kwargs):
- """
- Initialize.
-
- @keyword translator: the translator function to use.
-
- @keyword gettextFunction: The GNU gettext function to
- wrap. See class docstring.
-
- @param kwargs: keyword arguments for the translator function.
- """
- translator = kwargs.pop('translator', None)
- if translator is not None:
- self.translator = translator
- if self.translator is None:
- self.translator = self._gettextTranslation
-
- gettextFunction = kwargs.pop('gettextFunction', None)
- if gettextFunction is not None:
- self.gettextFunction = gettextFunction
-
- self.kwargs = kwargs
-
- def __call__(self, *args, **kwargs):
- """
- Translate a string.
-
- @param args: arguments to pass to translator, usually the
- string to translate, or for things like ungettext two strings
- and a number.
-
- @param kwargs: keyword arguments for the translator.
- Arguments given here will override the ones given at
- initialization.
-
- @return: a placeholder that will be translated
- when flattened.
-
- @rtype: PlaceHolder
- """
- kw = dict(self.kwargs)
- kw.update(kwargs)
- return PlaceHolder(self.translator, *args, **kw)
-
-
- _ = Translator()
-
- ungettext = Translator(gettextFunction='ungettext')
-
- def render(translator=None):
- """
- Render a localised message.
-
- >>> from nevow import i18n, rend
- >>> class MyPage(rend.Page):
- ... render_i18n = i18n.render()
-
- or, to use a specific domain:
-
- >>> from nevow import i18n, rend
- >>> _ = i18n.Translator(domain='foo')
- >>> class MyPage(rend.Page):
- ... render_i18n = i18n.render(translator=_)
-
- """
- if translator is None:
- translator = _
-
- def _render(page, ctx, data):
- # TODO why does this get page? Is it
- # the Page's self? Why would this look
- # like a bound method?
- children = ctx.tag.children
- ctx.tag.clear()
- for child in children:
- if isinstance(child, basestring):
- child = translator(child)
- ctx.tag[child]
- return ctx.tag
-
- return _render
-
- # TODO also provide macro()
-